﻿//-----------------------------------------------------------------------
// <copyright file="AssemblyDataContract.cs" company="CodePlex">
//     Copyright (c) Doug Holland, CodePlex. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace CodePlex.Diagnostics.Contracts
{
    using System;
    using System.Diagnostics;

    using System.Reflection;

    using System.Runtime.Serialization;

    /// <summary>
    /// Represents an assembly, which is a reusable, versionable, and self-describing building block of a common language runtime application.
    /// </summary>
    [DataContract(Name = "AssemblyDataContract", Namespace = "http://schemas.datacontract.org/2004/07/CodePlex.Diagnostics.Contracts")]
    public sealed class AssemblyDataContract : IExtensibleDataObject
    {
        #region public AssemblyDataContract(Assembly assembly)

        /// <summary>
        /// Initializes a new instance of the <see cref="T:AssemblyDataContract"/> class.
        /// </summary>
        /// <param name="assembly">The <see cref="T:System.Reflection.Assembly"/> for which the <see cref="T:CodePlex.Diagnostics.Contracts.AssemblyDataContract"/> is required.</param>
        public AssemblyDataContract(Assembly assembly)
        {
            this.CodeBase = assembly.CodeBase;

            if (assembly.EntryPoint != null)
            {
                this.EntryPoint = assembly.EntryPoint.Name;
            }
            
            this.FullName = assembly.FullName;

            this.GlobalAssemblyCache = assembly.GlobalAssemblyCache;

            this.HostContext = assembly.HostContext;

            this.ImageRuntimeVersion = assembly.ImageRuntimeVersion;

            this.Location = assembly.Location;

            if (assembly.ManifestModule != null)
            {
                this.ManifestModule = assembly.ManifestModule.FullyQualifiedName;
            }
            
            this.ReflectionOnly = assembly.ReflectionOnly;

            foreach (object attribute in assembly.GetCustomAttributes(false))
            {
                DebuggableAttribute debuggableAttribute = attribute as DebuggableAttribute;

                if (debuggableAttribute != null)
                {
                    this.DebugBuild = debuggableAttribute.IsJITTrackingEnabled;
                    
                    break;
                }
            }
        }

        #endregion

        #region public string CodeBase

        /// <summary>
        /// Gets the location of the assembly as specified originally, for example, in an <see cref="T:System.Reflection.AssemblyName"/> object.
        /// </summary>
        /// <value>The location of the assembly as specified originally, for example, in an <see cref="T:System.Reflection.AssemblyName"/> object.</value>
        [DataMember]
        public string CodeBase
        {
            get;
            private set;
        }

        #endregion

        #region public string EntryPoint

        /// <summary>
        /// Gets the entry point of this assembly.
        /// </summary>
        /// <value>The entry point of this assembly.</value>
        [DataMember]
        public string EntryPoint
        {
            get;
            private set;
        }

        #endregion

        #region public string FullName

        /// <summary>
        /// Gets the display name of the assembly.
        /// </summary>
        /// <value>The display name of the assembly.</value>
        [DataMember]
        public string FullName
        {
            get;
            private set;
        }

        #endregion

        #region public bool? GlobalAssemblyCache

        /// <summary>
        /// Gets a value indicating whether the assembly was loaded from the global assembly cache.
        /// </summary>
        /// <value><c>true</c> if the assembly was loaded from the global assembly cache; otherwise, <c>false.</c></value>
        [DataMember]
        public bool? GlobalAssemblyCache
        {
            get;
            private set;
        }

        #endregion

        #region public long? HostContext

        /// <summary>
        /// Gets the host context with which the assembly was loaded.
        /// </summary>
        /// <value>An <see cref="T:System.Int64"/> value that indicates the host context with which the assembly was loaded, if any.</value>
        [DataMember]
        public long? HostContext
        {
            get;
            private set;
        }

        #endregion

        #region public string ImageRuntimeVersion

        /// <summary>
        /// Gets a string representing the version of the common language runtime (CLR) saved in the file containing the manifest.
        /// </summary>
        /// <value>A string representing the CLR version folder name. This is not a full path.</value>
        [DataMember]
        public string ImageRuntimeVersion
        {
            get;
            private set;
        }

        #endregion

        #region public string Location

        /// <summary>
        /// Gets the path or UNC location of the loaded file that contains the manifest.
        /// </summary>
        /// <value>The location of the loaded file that contains the manifest.</value>
        [DataMember]
        public string Location
        {
            get;
            private set;
        }

        #endregion

        #region public string ManifestModule

        /// <summary>
        /// Gets the module that contains the manifest for the current assembly.
        /// </summary>
        /// <value>The module that contains the manifest for the current assembly.</value>
        [DataMember]
        public string ManifestModule
        {
            get;
            private set;
        }

        #endregion

        #region public bool? DebugBuild

        /// <summary>
        /// Gets a value indicating whether the assembly was compiled with full symbolic debug information.
        /// </summary>
        /// <value><c>true</c> if the assembly was compiled with full symbolic debug information; otherwise, <c>false</c>.</value>
        [DataMember]
        public bool? DebugBuild
        {
            get;
            private set;
        }

        #endregion

        #region public bool? ReflectionOnly

        /// <summary>
        /// Gets a value indicating whether this assembly was loaded into the reflection-only context.
        /// </summary>
        /// <value><c>true</c> if the assembly was loaded into the reflection-only context, rather than the execution context; otherwise, <c>false.</c></value>
        [DataMember]
        public bool? ReflectionOnly
        {
            get;
            private set;
        }

        #endregion

        #region ExtensionDataObject IExtensibleDataObject.ExtensionData

        /// <summary>
        /// Gets or sets the structure that contains extra data.
        /// </summary>
        /// <value>An <see cref="T:System.Runtime.Serialization.ExtensionDataObject"/> that contains data that is not recognized as belonging to the data contract.</value>
        ExtensionDataObject IExtensibleDataObject.ExtensionData
        {
            get;
            set;
        }

        #endregion
    }
}
